iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 29
0

前言

最後一天的系統開發學習我們來說明如何輸出地圖資料,可以輸出為PNG、JPEG與PDF的格式。

地圖列印功能建置

新增 AdvanceTool/ExportMap.html 頁面,預計要有以下選項提供使用者選擇:

  • 頁面大小:A0、A1、A3、A4(預設)、A5。
  • 解析度:72 dpi、150 dpi、200 dpi(預設)、300 dpi
  • 比例尺:1:500000、1:250000(預設)、1:100000、1:50000、1:25000、1:10000。
  • 輸出格式:PNG(預設)、JPEG、PDF。

由於列印功能需要 dom-to-image 的Library套件 dom-to-image-more.js,或是可選擇壓縮後的檔案 dom-to-image-more.min.js

產製PDF需要使用 jsPDF 的套件 jspdf.js

以上兩者下載後放入 js/Plug_in 資料夾中,並引入頁面當中。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <style>
        #exportmapseg tr {
            height:50px;
        }
    </style>
</head>
<body>
    <h2>地圖列印</h2>
    <div>
        <div id="exportmapseg" class="ui segment">
            <table style="width:100%;">
                <tbody>
                    <tr>
                        <td style="width:75px;">頁面大小</td>
                        <td>
                            <select class="ui fluid dropdown" id="format">
                                <option value="a0">A0 (slow)</option>
                                <option value="a1">A1</option>
                                <option value="a2">A2</option>
                                <option value="a3">A3</option>
                                <option value="a4" selected>A4</option>
                                <option value="a5">A5 (fast)</option>
                            </select>
                        </td>
                    </tr>
                    <tr>
                        <td>解析度</td>
                        <td>
                            <select class="ui fluid dropdown" id="resolution">
                                <option value="72">72 dpi (fast)</option>
                                <option value="150">150 dpi</option>
                                <option value="200" selected>200 dpi</option>
                                <option value="300">300 dpi (slow)</option>
                            </select>
                        </td>
                    </tr>
                    <tr>
                        <td>比例尺</td>
                        <td>
                            <select class="ui fluid dropdown" id="scale">
                                <option value="500">1:500000</option>
                                <option value="250" selected>1:250000</option>
                                <option value="100">1:100000</option>
                                <option value="50">1:50000</option>
                                <option value="25">1:25000</option>
                                <option value="10">1:10000</option>
                            </select>
                        </td>
                    </tr>
                    <tr>
                        <td>輸出格式</td>
                        <td>
                            <select class="ui fluid dropdown" id="imageformat">
                                <option value="PNG" selected>PNG</option>
                                <option value="JPEG">JPEG</option>
                                <option value="PDF">PDF</option>
                            </select>
                        </td>
                    </tr>
                </tbody>
            </table>
            <button type="button" style="margin-top:10px;" id="exportMapBtn" value="export" onclick="exportmap.WebMapExport()" class="fluid ui primary basic button">輸出</button>
        </div>
    </div>
    <script src="js/Plug_in/dom-to-image-more.js"></script>
    <script src="js/Plug_in/jspdf.js"></script>
    <script type="text/javascript" src="map_module/widget/AdvanceTool/jExportMap.js"></script>
    <script>
        $('.ui.dropdown').dropdown();
    </script>
</body>
</html>

系統畫面示意圖:
https://ithelp.ithome.com.tw/upload/images/20201009/20108631Nr89ZJC7es.png

列印功能寫在 AdvanceTool/jExportMap.js 中,撰寫 WebMapExport()
輸出的檔案名稱 ExportImageName 設為:MapExport_ + 當下的日期與時間;
撈取使用者設定的頁面大小、解析度、比例尺,計算影像的長度與寬度與圖面解析度,並自動依據數據移動地圖。
當移動完地圖、地圖也渲染完( rendercomplete )後,即要輸出地圖,依據選擇的 輸出格式 進行判斷,但不管哪一種都要使用 domtoimage,此library將圖面輸出為PNG或JPEG,若要輸出PDF則要使用 jsPDF 進行輸出。

var exportmap = function () {
    var dims = {
        a0: [1189, 841],
        a1: [841, 594],
        a2: [594, 420],
        a3: [420, 297],
        a4: [297, 210],
        a5: [210, 148]
    };

    var exportOptions = {
        filter: function (element) {
            var className = element.className || '';
            return (
                className.indexOf('ol-control') === -1 ||
                className.indexOf('ol-scale') > -1 ||
                (className.indexOf('ol-attribution') > -1 &&
                    className.indexOf('ol-uncollapsible'))
            );
        }
    };

    function WebMapExport (){
        var format = document.getElementById('format').value;
        var resolution = document.getElementById('resolution').value;
        var scale = document.getElementById('scale').value;
        var dim = dims[format];
        var width = Math.round((dim[0] * resolution) / 25.4);
        var height = Math.round((dim[1] * resolution) / 25.4);
        var viewResolution = map.getView().getResolution();
        var scaleResolution =
            scale /
            ol.proj.getPointResolution(
                map.getView().getProjection(),
                resolution / 25.4,
                map.getView().getCenter()
            );
        map.once('rendercomplete', function () {
            exportOptions.width = width;
            exportOptions.height = height;
            var ExportImageName = 'MapExport_' + new Date().Format("yyyyMMddhhmmss");
            var imageformat = document.getElementById('imageformat').value;
            if (imageformat === "PDF") {
                //輸出PDF
                domtoimage
                    .toJpeg(map.getViewport(), exportOptions)
                    .then(function (dataUrl) {
                        var pdf = new jsPDF('landscape', undefined, format);
                        pdf.addImage(dataUrl, 'JPEG', 0, 0, dim[0], dim[1]);
                        pdf.save(ExportImageName + '.pdf');
                        map.getTargetElement().style.width = '';
                        map.getTargetElement().style.height = '';
                        map.updateSize();
                        map.getView().setResolution(viewResolution);
                    });
            } else if (imageformat === "JPEG") {
                //輸出JPEG
                domtoimage.toJpeg(map.getViewport(), exportOptions)
                    .then(function (dataUrl) {
                        var link = document.createElement('a');
                        link.download = ExportImageName + '.jpeg';
                        link.href = dataUrl;
                        link.click();
                    });
            } else {
                //輸出PNG
                domtoimage.toPng(map.getViewport(), exportOptions)
                    .then(function (dataUrl) {
                        var link = document.createElement('a');
                        link.download = ExportImageName + '.png';
                        link.href = dataUrl;
                        link.click();
                    });
            }
        });
        map.getTargetElement().style.width = width + 'px';
        map.getTargetElement().style.height = height + 'px';
        map.updateSize();
        map.getView().setResolution(scaleResolution);
    }

    return {
        WebMapExport: WebMapExport
    };
}();

輸出PDF成果示意圖:
https://ithelp.ithome.com.tw/upload/images/20201009/201086317vbCi7BfZR.png

小結

Day 29 是最後一篇系統開發文章了,終於快結束了!!!今天學會了怎麼把圖面上的成果進行輸出,但今天學習的內容比較淺,可以自行多加一些功能上去,像是在選擇頁面大小與解析度時,可以放一個polygon顯示在地圖上,表示該大小為輸出的範圍 等。

明天最後一天就來總結我們這30天的學習內容與結賽的感想。


上一篇
Day 28. 全台GPS三維形變時序資料查詢
下一篇
Day 30. 以WebGIS為主題的鐵人賽30天完賽心得
系列文
WebGIS入門學習 - 以Openlayers實作30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言